package com.young.netty.gateway.gateway;

import com.young.netty.gateway.config.NettyGatewayConfig;
import com.young.netty.gateway.interceptor.InterceptorChain;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ConnectTimeoutException;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;
import lombok.extern.slf4j.Slf4j;

/**
 * Netty网关
 *
 * @author Young
 * @Date 2021-07-24 19:17
 */
@Slf4j
public class NettyGateway {

    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    private ChannelFuture channelFuture;

    private InterceptorChain interceptorChain;

    private NettyGatewayConfig nettyGatewayConfig;

    public NettyGateway(InterceptorChain interceptorChain, NettyGatewayConfig nettyGatewayConfig) {
        this.interceptorChain = interceptorChain;
        this.nettyGatewayConfig = nettyGatewayConfig;
    }


    public void start() {
        log.info("Netty Nio Server starting...");
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        ServerBootstrap serverBootstrap = new ServerBootstrap()
                .group(bossGroup, workerGroup)
                // 说明一个新的Channel如何接收进来的连接
                .channel(NioServerSocketChannel.class)
                // tcp最大缓存链接个数
                .option(ChannelOption.SO_BACKLOG, 1024)
                //保持连接
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childOption(ChannelOption.TCP_NODELAY, true)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) {
                        // 网络超时时间
                        socketChannel.pipeline()
                                // 请求消息解码器
                                .addLast(new HttpRequestDecoder())
                                // 目的是将多个消息转换为单一的request或者response对象
                                .addLast(new HttpObjectAggregator(65535))
                                // 响应编码器
                                .addLast(new HttpResponseEncoder())
                                // 目的是支持异步大文件传输（）
                                .addLast(new ChunkedWriteHandler())
                                // 处理接收到的请求， 这里相当于过滤器，可以配置多个
                                .addLast(new NettyNioServerHandler(interceptorChain));
                    }
                });

        try {
            ChannelFuture channelFuture = serverBootstrap.bind("127.0.0.1", nettyGatewayConfig.getServerPort()).sync();
            this.bossGroup = bossGroup;
            this.workerGroup = workerGroup;
            this.channelFuture = channelFuture;
            log.info("Netty Nio Server started...");
            // 等待服务端口的关闭；在这个例子中不会发生，但你可以优雅实现；关闭你的服务
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            log.error(e.getMessage());
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    /**
     * 关闭NettyGateway
     */
    public void shoudown() {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }


}
